package engine.dojo;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.*;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import util.Parameters;
import util.Util;

import engine.HTMLBuilder;
import engine.dojo.element.ButtonManager;
import engine.dojo.element.ListItemManager;
import engine.dojo.element.RoundRectListManager;
import entity.Project;

public class DojoHTMLBuilder extends HTMLBuilder{
	
	@Override
	public boolean generateCode(Project project) {
		
		File in = new File(Parameters.HTML_ROOT + "index.html");
		FileWriter fstream = null;
		BufferedWriter out = null;
		Document doc = null;
		
		createHTMLPage();
		
		try{
			doc = Jsoup.parse(in, "ISO-8859-1");
		}catch(IOException e){
			e.printStackTrace();
		}
		
		Element head = doc.head();
		Element body = doc.body();

		head.append("<script type='text/javascript' " +
						"src='"+DojoParameters.DOJO_JS_PATH+"' " +
						"djConfig='parseOnLoad:true'>" +
					"</script>" +
					
					"<link rel='stylesheet' type='text/css'" +
					"href='"+DojoParameters.TUNDRA_CSS_PATH+"'>" +
					
					"<link rel='stylesheet' type='text/css' " +
						"href='"+DojoParameters.MOBILE_IPHONE_CSS_PATH+"'>" +
					
					"<script type='text/javascript' id='dojoRequire'>" +
						"dojo.require('dojo.parser');"+
						"dojo.require('dojox.mobile');"+
						"dojo.requireIf(!dojo.isWebKit, 'dojox.mobile.compat');"+
					"</script>" +
					
					"<script type='text/javascript' id='functions' src='functions.js'></script>"+
					"<script type='text/javascript' id='functions' src='restService.js'></script>"
		);
		
		body.addClass("tundra");
		navigateThrowGUIDescriptor(project.getGuiDescriptor(), doc, null);
		
		try{
			  fstream = new FileWriter(Parameters.HTML_ROOT + "index.html", false);
			  out = new BufferedWriter(fstream);
			  out.write(doc.toString());
			  //Close the output stream
			  out.close();
		}catch (IOException e){
			  e.printStackTrace();
		}
		
		Util.logNL(doc.html());
		
		return true;
	}
	
	private void createHTMLPage(){

		FileWriter fstream = null;
		BufferedWriter out = null;
		
		try{
			  fstream = new FileWriter(Parameters.HTML_ROOT + "index.html", false);
			  out = new BufferedWriter(fstream);
			  out.write("" +
			  		"<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>" +
			  		"<html>" +
			  		"<head>" +
			  		"<meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>" +
			  		"<title>GUI Generated</title>" +
			  		"</head>" +
			  		"<body>" +
			  		"</body>" +
			  		"</html>"
				);
			  //Close the output stream
			  out.close();
		}catch (IOException e){
			  e.printStackTrace();
		}
	}
	
	private void navigateThrowGUIDescriptor(JSONArray elements, Document doc, JSONObject parent){
		
		JSONObject element = null;
		
		for(int i=0; i<elements.length(); i++){
			try{
				element = elements.getJSONObject(i);
				generateDom(element, doc, parent);
				if(element.getJSONArray("children").length()>0){
					navigateThrowGUIDescriptor(element.getJSONArray("children"), doc, element);
				}
			}catch(JSONException e){
				e.printStackTrace();
			}
		}
	}
	
	private void generateDom(JSONObject element, Document doc, JSONObject parent){
		
		Element body = doc.body();
		
		try{
			switch(element.getString("element")){
			
			case "mobileButton":
				Element button = doc.createElement("button");
				button.attr("dojoType", DojoParameters.DOJOX_MOBILE_BUTTON);
				button.attr("id", element.getString("id"));
				
				JSONObject buttonAttributes = ButtonManager.specializeButton(element);
				
				addAttributoToDom(buttonAttributes, button);
				addDomToParent(button, parent, doc);
				
				includeLibrary(DojoParameters.DOJOX_MOBILE_BUTTON, doc);
				break;
				
			case "heading":
				Element heading = doc.createElement("h1");
				heading.attr("dojoType", DojoParameters.DOJOX_MOBILE_HEADING);
				heading.attr("id", element.getString("id"));
				
				addAttributoToDom(element, heading);
				addDomToParent(heading, parent, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_HEADING, doc);
				break;
				
			case "listItem":
				Element listItem = doc.createElement("li");
				listItem.attr("dojoType", DojoParameters.DOJOX_MOBILE_LIST_ITEM);
				listItem.attr("id", element.getString("id"));
				
				JSONObject listItemAttributes = ListItemManager.specializeListItem(element);
				
				addAttributoToDom(listItemAttributes, listItem);
				addDomToParent(listItem, parent, doc);
				
				includeLibrary(DojoParameters.DOJOX_MOBILE_HEADING, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_LIST_ITEM, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_OVERLAY, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_SPINWHEEL, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_SPINWHEELSLOT, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_TOOLBARBUTTON, doc);
				break;
				
			case "roundRect":
				Element roundRect = doc.createElement("div");
				roundRect.attr("dojoType", DojoParameters.DOJOX_MOBILE_ROUND_RECT);
				roundRect.attr("id", element.getString("id"));
				addAttributoToDom(element, roundRect);
				addInnerHTMLToDom(element, roundRect);
				addDomToParent(roundRect, parent, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_ROUND_RECT, doc);
				break;
				
			case "roundRectCategory":
				Element roundRectCategory = doc.createElement("h2");
				roundRectCategory.attr("dojoType", DojoParameters.DOJOX_MOBILE_ROUND_RECT_CATEGORY);
				roundRectCategory.attr("id", element.getString("id"));
				
				addAttributoToDom(element, roundRectCategory);
				addDomToParent(roundRectCategory, parent, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_ROUND_RECT_CATEGORY,doc);
				break;
				
			case "roundRectList":
				Element roundRectList = doc.createElement("div");
				roundRectList.attr("dojoType", DojoParameters.DOJOX_MOBILE_ROUND_RECT_LIST);
				roundRectList.attr("id", element.getString("id"));
				
				JSONObject roundRectListAttributes = RoundRectListManager.specializeRoundRectList(element);
				
				addAttributoToDom(roundRectListAttributes, roundRectList);
				
				addDomToParent(roundRectList, parent, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_ROUND_RECT_LIST,doc);
				includeLibrary(DojoParameters.WIDGETS_DETAILS,doc);
				break;
				
			case "tabbar":
				Element tabbar = doc.createElement("ul");
				tabbar.attr("dojoType", DojoParameters.DOJOX_MOBILE_TABBAR);
				tabbar.attr("id", element.getString("id"));
				
				addAttributoToDom(element, tabbar);
				addDomToParent(tabbar, parent, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_TABBAR,doc);
				break;
				
			case "tabbarButton":
				Element tabbarButton = doc.createElement("li");
				tabbarButton.attr("dojoType", DojoParameters.DOJOX_MOBILE_TABBAR_BUTTON);
				tabbarButton.attr("id", element.getString("id"));
				
				addAttributoToDom(element, tabbarButton);
				addDomToParent(tabbarButton, parent, doc);
				includeLibrary(DojoParameters.DOJOX_MOBILE_TABBAR_BUTTON,doc);
				break;
			
			case "view":
				Element view = doc.createElement("div");
				view.attr("dojoType", DojoParameters.DOJOX_MOBILE_VIEW);
				view.attr("id", element.getString("id"));
				
				addAttributoToDom(element, view);
				
				body.appendChild(view);
				includeLibrary(DojoParameters.DOJOX_MOBILE_VIEW, doc);
				break;
				
			default:
				System.err.println("Elemento sconosciuto");
			}			
		}catch(JSONException e){
			e.printStackTrace();
		}
	}
	
	private void addDomToParent(Element dom, JSONObject parent, Document doc){
		
		try{
			doc.getElementById(parent.getString("id")).append(dom.toString());
		}catch (JSONException e) {
			e.printStackTrace();
		}
	}
	
	private void addAttributoToDom(JSONObject element, Element dom){

		JSONObject attributes = null;
		String[] keys = null;
		
		try{
			
			System.out.println(element);
			
			attributes = element.getJSONObject("attributes");
			keys = JSONObject.getNames(attributes);
			
			if(keys!=null){
				for(int i=0; i<keys.length; i++){
					System.out.println(keys[i]);
					
					dom.attr(keys[i], attributes.getString(keys[i]));
				}
			}
			
		}catch(JSONException e){
			e.printStackTrace();
		}
		
		
//		
//		JSONArray attributes = null;
//		
//		try{
//			attributes = element.getJSONArray("attributes");
//			if(attributes.length()>0){
//				for(int i=0; i<attributes.length(); i++){
//					JSONObject jo = attributes.getJSONObject(i);
//					JSONArray a = jo.names();
//					dom.attr((String)a.get(0), jo.getString( (String)(a.get(0)) ));
//				}
//			}
//		}catch(JSONException e){
//			e.printStackTrace();
//		}
	}
	
	private void addInnerHTMLToDom(JSONObject element, Element dom){
		
		try{
			if(element.getString("innerHTML")!=""){
				dom.append(element.getString("innerHTML"));
			}
		}catch(JSONException e){
			e.printStackTrace();
		}
		
	}
	
	private void includeLibrary(String elementType, Document doc){
	
		Element head = doc.head();
		
		if(!head.getElementById("dojoRequire").html().contains(elementType)){
			head.getElementById("dojoRequire").append("dojo.require('"+elementType+"');\n");
		}
	}
}
